/// File: InstallerActions\VSLabInstaller.cs
/// 
/// Author: Antonio Cisternino (cisterni@di.unipi.it)
///   
/// ------------------------------------------------------------
/// Copyright (c) Microsoft Corporation.  All rights reserved.
/// 
/// The use and distribution terms for this software are 
/// contained in the file named license.txt, which can be found 
/// in the root of this distribution.
/// By using this software in any fashion, you are agreeing to 
/// be bound by the terms of this license.
///
/// You must not remove this notice, or any other, from this
/// software.
/// ------------------------------------------------------------

using System;
using System.IO;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using Microsoft.Win32;
using SetupActions;
using System.Windows.Forms;

namespace VSLabInstaller
{
    [RunInstaller(true)]
    public class VSLabInstaller : ProjectInstaller
    {
        private const string vskey = @"SOFTWARE\Microsoft\VisualStudio";
        private const string filetemplates = @"SOFTWARE\Microsoft\VisualStudio\9.0\Projects\{f2a71f9b-5d33-465a-a702-920d77279786}\AddItemTemplates\TemplateDirs\{f2a71f9b-5d33-465a-a702-920d77279786}\/1";
        private const string projecttemplates = @"SOFTWARE\Microsoft\VisualStudio\9.0\NewProjectTemplates\TemplateDirs\{91a04a73-4f2c-4e7c-ad38-c1a68e7da05c}\/2";
        private const string packages = @"\Packages";
        private const string assemblyFolders = @"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders";
        private const string hackfsc = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\fsc.exe";
        private const string product = @"SOFTWARE\Unipi\VSLab";
        private const string publicassemblies = @"Common7\IDE\PublicAssemblies";
        private const string netassemblyfolders = @"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\VSLab";

        private string GetFSharpBinPath()
        {
            var ret = "";
            using (RegistryKey k = Registry.LocalMachine.OpenSubKey(assemblyFolders))
            {
                string keyname = null;
                foreach (var skn in k.GetSubKeyNames())
                    if (skn.StartsWith("Microsoft.FSharp-"))
                    {
                        keyname = skn;
                        break;
                    }
                if (keyname == null)
                {
                    System.Diagnostics.Process.Start("http://msdn.microsoft.com/fsharp/");
                    throw new Exception("You must install F# with Visual Studio extensions in order to use VSLab");
                }
                using (RegistryKey sk = k.OpenSubKey(keyname))
                {
                    ret = (string)sk.GetValue(null);
                }
            }
            return ret.Replace("\\\\", "\\");
        }

        public override void Install(IDictionary savedState)
        {
            base.Install(savedState);
            int idx = Array.IndexOf<string>(VisualStudioVersions, "9.0");
            if (idx == -1)
                throw new Exception("Visual Studio 2008 is required in order to run VSLab");

            // Copy files to bin
            var fs = GetFSharpBinPath();
            var vslab = TargetDir;
            var vsdir = GetVisualStudioBaseDir("9.0");

            if (!fs.EndsWith("\\")) fs += "\\";
            if (!vslab.EndsWith("\\")) vslab += "\\";
            if (!vsdir.EndsWith("\\")) vsdir += "\\";

            // Packages
            if (Context.Parameters["InstallPackage3DChart"] == "1")
                CopyFile(0, vslab + @"vslabchart3dpackage.dll", vslab + "packages");
            if (Context.Parameters["InstallPackageChart"] == "1")
                CopyFile(0, vslab + @"vslabchartpackage.dll", vslab + "packages");
            if (Context.Parameters["InstallPackageShell"] == "1")
                CopyFile(0, vslab + @"vslabshellpackage.dll", vslab + "packages");

            if (File.Exists(vslab + @"VStudio\VSLab_Projects\vslabProject.fsproj"))
                File.Delete(vslab + @"VStudio\VSLab_Projects\vslabProject.fsproj");
            using (var prjf = File.CreateText(vslab + @"VStudio\VSLab_Projects\vslabProject.fsproj"))
            {
                prjf.Write(InstallerActions.Properties.Resources.FSharpProjectTemplate, vslab, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Unipi\\VSLab\\packages");
                RegisterFileOrDirectory(0, vslab + @"VStudio\VSLab_Projects\vslabProject.fsproj");
            }
            if (File.Exists(vslab + @"vslabstartup.fsx"))
                File.Delete(vslab + @"vslabstartup.fsx");
            using (var startup = File.CreateText(vslab + @"vslabstartup.fsx"))
            {
                startup.Write(InstallerActions.Properties.Resources.VSLabStartupTemplate, vsdir + publicassemblies);
                RegisterFileOrDirectory(0, vslab + @"vslabstartup.fsx");
            }

            // Registry entries
            SetRegistryValue(0, Registry.LocalMachine, product, "FSharpBin", fs);
            SetRegistryValue(0, Registry.LocalMachine, product, "VSLabDir", vslab);
            SetRegistryValue(0, Registry.LocalMachine, vskey + @"\9.0\AutomationOptions\LookInFolders", vslab, "");
            SetRegistryValue(0, Registry.LocalMachine, netassemblyfolders, null, vslab);
            SetRegistryValue(0, Registry.LocalMachine, netassemblyfolders, "Description", "VSLab library directory");
            // New Item templates
            SetRegistryValue(0, Registry.LocalMachine, filetemplates, null, "VSLab");
            SetRegistryValue(0, Registry.LocalMachine, filetemplates, "SortPriority", 20);
            SetRegistryValue(0, Registry.LocalMachine, filetemplates, "TemplatesDir", vslab + @"VStudio\VSLab_Files");
            // New Project templates
            SetRegistryValue(0, Registry.LocalMachine, projecttemplates, null, "Visual F#");
            SetRegistryValue(0, Registry.LocalMachine, projecttemplates, "SortPriority", 100);
            SetRegistryValue(0, Registry.LocalMachine, projecttemplates, "TemplatesDir", vslab + @"VStudio\VSLab_Projects");
        }

        //    public static void Main(string[] args) {
        //      ACSInstaller a = new ACSInstaller();
        //      a.Context = new InstallContext();
        //      a.Context.Parameters["TargetDir"] = @"c:\test";
        //      a.Context.Parameters["InstallType"] = "2";
        //      Hashtable state = new Hashtable();
        //      a.Install(state);
        //      a.Uninstall(state);
        //    }
    }
}
